#include "./observe.h"

#include "../ecs/ecs.hpp"
#include "qlib/all.h"

#include "../select/select.hpp"

namespace qbe::observe {

template <typename T, typename... Args>
std::string getEntityNameOfCellElemnt_impl(entt::registry& reg, entt::entity e) {
  auto ptr = reg.try_get<std::shared_ptr<T>>(e);

  if (ptr != nullptr) {
    auto type_index = std::type_index(typeid(T));
    return type_index.name();
  }

  if constexpr (sizeof...(Args) > 0) {
    return getEntityNameOfCellElemnt_impl<Args...>(reg, e);
  } else {
    return "None";
  }
}

std::string getEntityNameOfCellElemnt(entt::registry& reg, entt::entity e) {
  return getEntityNameOfCellElemnt_impl<QLIB_CELL_ELEMENT_TYPE>(reg, e);
}

template <typename ComponentType>
void componentCreate(entt::registry& reg) {
  reg.on_construct<ComponentType>().connect<&componentCreate_impl<ComponentType>>();
}

template <typename ComponentType>
void componentUpdate(entt::registry& reg) {
  reg.on_update<ComponentType>().connect<&componentUpdate_impl<ComponentType>>();
}

template <typename ComponentType>
void componentDestry(entt::registry& reg) {
  reg.on_destroy<ComponentType>().connect<&componentDestry_imple<ComponentType>>();
}

// 实体增删改，可打断点监控
void entityCreate(entt::registry& reg, entt::entity e) {
  std::string info;

  info = "Observe create entity: " + std::to_string((uint32_t)e) + "\n";
  info += "    ElementType: " + getEntityNameOfCellElemnt(reg, e);

  SPDLOG_INFO(info);
}
void entityUpdate(entt::registry& reg, entt::entity e) {
  std::string info;

  info = "Observe update entity: " + std::to_string((uint32_t)e) + "\n";
  info += "    ElementType: " + getEntityNameOfCellElemnt(reg, e);

  SPDLOG_INFO(info);
}
void entityDestry(entt::registry& reg, entt::entity e) {
  std::string info;

  info = "Observe destry entity: " + std::to_string((uint32_t)e) + "\n";
  info += "    ElementType: " + getEntityNameOfCellElemnt(reg, e);

  SPDLOG_INFO(info);
}

void init(ecs::Query query) {
  auto cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  // 监控实体增删改
  reg.on_construct<entt::entity>().connect<&entityCreate>();
  reg.on_update<entt::entity>().connect<&entityUpdate>();
  reg.on_destroy<entt::entity>().connect<&entityDestry>();

  // 监控选中组件增删，可添加其他组件，Tag组件不能监控update
  componentCreate<select::SelectTag>(reg);
  componentDestry<select::SelectTag>(reg);
}

void Plugin::build(ecs::App& app) {
  app.add_systems<ecs::stage::Startup>(init);
}

}  // namespace qbe::observe